package cn.edu.scnu.semart.order.service.impl;

import cn.edu.scnu.semart.model.user.Address;
import cn.edu.scnu.semart.model.cart.CartItemDTO;
import cn.edu.scnu.semart.model.goods.Goods;
import cn.edu.scnu.semart.model.order.*;
import cn.edu.scnu.semart.order.feign.CartFeignClient;
import cn.edu.scnu.semart.order.feign.GoodsFeignClient;
import cn.edu.scnu.semart.order.feign.UserFeignClient;
import cn.edu.scnu.semart.order.mapper.OrderMapper;
import cn.edu.scnu.semart.order.service.OrderService;
import cn.edu.scnu.semart.order.service.PaymentService;
import cn.edu.scnu.semart.order.untils.BusinessException;
import cn.edu.scnu.semart.order.untils.SnowFlake;

import cn.edu.scnu.semart.vo.order.OrderQueryVo;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class OrderServiceImpl implements OrderService {
    @Autowired
    private final OrderMapper orderMapper;
    @Autowired
    private final UserFeignClient userFeignClient;
    @Autowired
    private final GoodsFeignClient goodsFeignClient;
    @Autowired
    private final CartFeignClient cartFeignClient;
    @Autowired
    private final PaymentService paymentService;

    private final SnowFlake snowFlake = new SnowFlake(); // 分布式ID生成器

    @Override
    @Transactional
    public OrderDTO createOrder(Integer userId, Integer addressId) {
        // 1. 验证地址
        Address address = userFeignClient.getAddressById(userId, addressId);
        if (address == null) {
            throw new BusinessException("收货地址不存在");
        }

        // 2. 获取购物车选中商品 - 使用新的Feign接口方法
        List<CartItemDTO> cartItems;
        try {
            // 使用新接口直接获取购物车项列表，避免类型转换问题
            cartItems = cartFeignClient.getCartItems(userId);
        } catch (Exception e) {
            throw new BusinessException("获取购物车失败: " + e.getMessage());
        }

        if (cartItems == null) {
            throw new BusinessException("获取购物车数据失败，购物车项为null");
        }

        if (cartItems.isEmpty()) {
            throw new BusinessException("购物车中没有商品");
        }

        // 筛选出选中的购物车项
        List<CartItemDTO> selectedItems = cartItems.stream()
                .filter(item -> Boolean.TRUE.equals(item.getSelected()))
                .collect(Collectors.toList());

        if (selectedItems.isEmpty()) {
            throw new BusinessException("购物车中没有选中的商品，请先选择要购买的商品");
        }

        // 检查商品库存和信息是否完整
        List<String> invalidItems = new ArrayList<>();
        for (CartItemDTO item : selectedItems) {
            if (item.getProductName() == null || item.getProductPrice() == null) {
                invalidItems.add("商品ID: " + item.getProductId() + " 信息不完整");
            }
        }

        if (!invalidItems.isEmpty()) {
            throw new BusinessException("购物车中存在无效商品: " + String.join(", ", invalidItems));
        }

        // 3. 获取商品详情并验证
        List<Integer> productIds = selectedItems.stream()
                .map(CartItemDTO::getProductId)
                .collect(Collectors.toList());

        List<Goods> products = goodsFeignClient.getBatchByIds(productIds);
        Map<Integer, Goods> productMap = products.stream()
                .collect(Collectors.toMap(Goods::getId, p -> p));

        // 验证商品状态和库存
        Map<Integer, Integer> deductMap = new HashMap<>();
        BigDecimal totalPrice = BigDecimal.ZERO;
        List<OrderItem> orderItems = new ArrayList<>();

        for (CartItemDTO item : selectedItems) {
            Goods product = productMap.get(item.getProductId());
            if (product == null || 1 != (product.getStatus())) {
                throw new BusinessException("商品[" + item.getProductName() + "]已下架");
            }
            if (product.getStock() < item.getQuantity()) {
                throw new BusinessException("商品[" + item.getProductName() + "]库存不足");
            }

            // 计算总价
            BigDecimal itemTotal = product.getPrice().multiply(BigDecimal.valueOf(item.getQuantity()));
            totalPrice = totalPrice.add(itemTotal);

            // 创建订单项
            OrderItem orderItem = new OrderItem();
            orderItem.setProductId(item.getProductId());
            orderItem.setProductName(item.getProductName());
            orderItem.setProductDescription(product.getDescription());
            orderItem.setProductPrice(product.getPrice());
            orderItem.setQuantity(item.getQuantity());
            orderItem.setProductImage(product.getMainImage());
            orderItem.setSellerId(product.getUserId());
            orderItem.setSellerName(product.getUserName());
            orderItems.add(orderItem);

            // 准备扣减库存
            deductMap.put(item.getProductId(), item.getQuantity());
        }

        // 4. 创建订单
        Order order = new Order();
        order.setOrderNumber(String.valueOf(snowFlake.nextId()));
        order.setPayTradeNo(String.valueOf(snowFlake.nextId()));
        order.setUserId(userId);
        order.setAddressId(addressId);
        order.setTotalPrice(totalPrice);
        order.setStatus("pending_payment");
        order.setCreateTime(new Date());

        orderMapper.insertOrder(order);
        orderMapper.insertOrderItems(order.getOrderId(), orderItems);

        // 5. 扣减库存
        if (!goodsFeignClient.deductStock(deductMap)) {
            throw new BusinessException("扣减库存失败");
        }

        // 6. 创建支付记录
        paymentService.createPayment(order.getOrderNumber(), totalPrice);

        // 创建订单DTO
        OrderDTO orderDTO = convertToDTO(order, orderItems, address);

        try {
            // 7. 清空购物车 - 移到最后执行，确保前面所有操作都成功
            List<Integer> cartIds = selectedItems.stream()
                    .map(CartItemDTO::getCartId)
                    .collect(Collectors.toList());
            cartFeignClient.batchDelete(cartIds);
        } catch (Exception e) {
            // 购物车清空失败不影响订单创建
            // 只记录日志，不抛出异常
            System.err.println("清空购物车失败: " + e.getMessage());
        }

        return orderDTO;
    }

    @Override
    public OrderDTO getOrderDetails(Integer orderId) {
        // 1. 获取订单基本信息
        Order order = orderMapper.selectOrderById(orderId);
        if (order == null) {
            throw new BusinessException("订单不存在");
        }

        // 2. 获取地址信息
        Address address = userFeignClient.getAddressById(order.getUserId(), order.getAddressId());

        // 3. 获取订单项
        List<OrderItem> orderItems = orderMapper.selectOrderItems(orderId);

        // 4. 转换为DTO
        return convertToDTO(order, orderItems, address);
    }

    @Override
    @Transactional // 必须添加此注解确保操作在事务中执行
    public void updateOrderStatus(Integer orderId, String status) {
        // 验证状态是否有效
        if (!Arrays.asList("pending_payment", "pending_delivery", "pending_receipt", "completed", "canceled").contains(status)) {
            throw new BusinessException("无效的订单状态");
        }

        // 获取当前订单状态
        String currentStatus = orderMapper.getOrderStatus(orderId);

        // 状态转换验证
        if ("completed".equals(currentStatus) || "canceled".equals(currentStatus)) {
            throw new BusinessException("已完成或已取消的订单不能修改状态");
        }

        // 更新状态
        orderMapper.updateOrderStatus(orderId, status);
        // 如果是支付成功，设置支付时间
        if ("pending_delivery".equals(status)) {
            orderMapper.updatePaymentTime(orderId, new Date());
        }

        // 如果是取消订单，需要恢复库存
        if ("canceled".equals(status)) {
            // 1. 根据订单ID查询订单项
            List<OrderItem> orderItems = orderMapper.selectOrderItems(orderId);

            // 2. 构建商品ID和数量的 Map
            Map<Integer, Integer> restoreMap = orderItems.stream()
                    .collect(Collectors.toMap(
                            OrderItem::getProductId,
                            OrderItem::getQuantity
                    ));

            // 3. 调用 Feign 客户端恢复库存
            if (!goodsFeignClient.restoreStock(restoreMap)) {
                throw new BusinessException("恢复库存失败");
            }
        }
    }

    // 自动确认收货定时任务
    @Scheduled(cron = "0 0 2 * * ?") // 每天凌晨2点执行
    @Transactional
    @Override
    public void autoConfirmReceipt() {
        // 查找7天前已发货的订单
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DAY_OF_MONTH, -7);
        Date tenDaysAgo = cal.getTime();

        List<Order> orders = orderMapper.selectOrdersForAutoConfirm(tenDaysAgo);

        for (Order order : orders) {
            orderMapper.updateOrderStatus(order.getOrderId(), "completed");
            orderMapper.updateCompleteTime(order.getOrderId(), new Date());

        }
    }

    // 订单统计
    @Override
    public OrderStatistics getOrderStatistics(Date start, Date end, String granularity) {
        OrderStatistics statistics = new OrderStatistics();
        statistics.setPeriod(granularity);

        // 根据粒度获取数据
        switch (granularity) {
            case "daily":
                List<Map<String, Object>> dailyData = orderMapper.getDailySales(start, end);
                // 处理数据...
                break;
            case "monthly":
                // 类似处理
                break;
        }

        // 获取地域销量
        List<Map<String, Object>> regionData = orderMapper.getRegionSales(start, end);
        Map<String, BigDecimal> regionSales = regionData.stream()
                .collect(Collectors.toMap(
                        m -> (String) m.get("province"),
                        m -> (BigDecimal) m.get("sales")
                ));
        statistics.setRegionSales(regionSales);

        return statistics;
    }

    // 支付回调处理
    @Override
    @Transactional
    public void handlePaymentCallback(String orderNumber, boolean success) {
        if (success) {
            orderMapper.updateOrderPaymentStatus(orderNumber, "pending_delivery");
        } else {
            // 支付失败，恢复库存
            List<OrderItem> items = orderMapper.selectOrderItemsByOrderNumber(orderNumber);
            Map<Integer, Integer> restoreMap = items.stream()
                    .collect(Collectors.toMap(OrderItem::getProductId, OrderItem::getQuantity));

            // 调用商品服务恢复库存
            goodsFeignClient.restoreStock(restoreMap);

            orderMapper.updateOrderPaymentStatus(orderNumber, "canceled");
        }
    }

    private OrderDTO convertToDTO(Order order, List<OrderItem> items, Address address) {
        OrderDTO dto = new OrderDTO();
        dto.setOrderId(order.getOrderId());
        dto.setOrderNumber(order.getOrderNumber());
        dto.setUserId(order.getUserId());
        dto.setTotalPrice(order.getTotalPrice());
        dto.setStatus(order.getStatus());
        dto.setCreateTime(order.getCreateTime());
        dto.setPayTradeNo(order.getPayTradeNo());

        // 地址信息
        if (address != null) {
            AddressDTO addressDTO = new AddressDTO();
            addressDTO.setRecipient(address.getRecipient());
            addressDTO.setPhone(address.getPhone());

            // 安全处理地址字符串拼接，避免null值
            String province = address.getProvince() != null ? address.getProvince() : "";
            String city = address.getCity() != null ? address.getCity() : "";
            String district = address.getDistrict() != null ? address.getDistrict() : "";
            String street = address.getStreet() != null ? address.getStreet() : "";
            String detail = address.getDetail() != null ? address.getDetail() : "";

            addressDTO.setFullAddress(province + city + district + street + detail);
            dto.setAddress(addressDTO);
        } else {
            // 提供默认地址对象，避免NPE
            AddressDTO addressDTO = new AddressDTO();
            addressDTO.setRecipient("未知收件人");
            addressDTO.setPhone("未知电话");
            addressDTO.setFullAddress("地址信息不可用");
            dto.setAddress(addressDTO);
        }

        // 订单项
        List<OrderItemDTO> itemDTOs = items.stream().map(item -> {
            OrderItemDTO itemDTO = new OrderItemDTO();
            itemDTO.setProductId(item.getProductId());
            itemDTO.setProductName(item.getProductName());
            itemDTO.setProductDescription(item.getProductDescription());
            itemDTO.setPrice(item.getProductPrice());
            itemDTO.setQuantity(item.getQuantity());
            itemDTO.setProductImage(item.getProductImage());
            itemDTO.setSellerId(item.getSellerId());
            itemDTO.setSellerName(item.getSellerName());
            return itemDTO;
        }).collect(Collectors.toList());

        dto.setItems(itemDTOs);
        return dto;
    }

    @Override
    public List<OrderDTO> getUserOrders(Integer userId, String status) {
        // 1. 查询用户的所有订单
        List<Order> orders = orderMapper.selectOrdersByUserIdAndStatus(userId, status);
        if (orders.isEmpty()) {
            return Collections.emptyList();
        }

        // 2. 获取订单ID列表
        List<Integer> orderIds = orders.stream()
                .map(Order::getOrderId)
                .collect(Collectors.toList());

        // 3. 批量查询订单项
        List<OrderItem> allItems = orderMapper.selectOrderItemsByOrderIds(orderIds);
        Map<Integer, List<OrderItem>> itemsMap = allItems.stream()
                .collect(Collectors.groupingBy(OrderItem::getOrderId));

        // 4. 获取地址ID列表
        List<Integer> addressIds = orders.stream()
                .map(Order::getAddressId)
                .distinct()
                .collect(Collectors.toList());
        // 5. 批量查询地址信息
        List<Address> addresses = userFeignClient.getAddressesByIds(addressIds);
        Map<Integer, Address> addressMap = addresses.stream()
                .collect(Collectors.toMap(Address::getAddressId, a -> a));

        // 6. 组装DTO
        return orders.stream().map(order -> {
            OrderDTO dto = new OrderDTO();
            dto.setOrderId(order.getOrderId());
            dto.setOrderNumber(order.getOrderNumber());
            dto.setUserId(order.getUserId());
            dto.setTotalPrice(order.getTotalPrice());
            dto.setStatus(order.getStatus());
            dto.setCreateTime(order.getCreateTime());
            dto.setPaymentTime(order.getPaymentTime());
            dto.setDeliveryTime(order.getDeliveryTime());
            dto.setCompleteTime(order.getCompleteTime());


            // 设置地址
            Address address = addressMap.get(order.getAddressId());
            if (address != null) {
                AddressDTO addressDTO = new AddressDTO();
                addressDTO.setRecipient(address.getRecipient());
                addressDTO.setPhone(address.getPhone());
                addressDTO.setFullAddress(
                        address.getProvince() + address.getCity() +
                                address.getDistrict() + address.getStreet() + address.getDetail()
                );
                dto.setAddress(addressDTO);
            }
            // 设置订单项
            List<OrderItem> items = itemsMap.get(order.getOrderId());
            if (items != null) {
                List<OrderItemDTO> itemDTOs = items.stream().map(item -> {
                    OrderItemDTO itemDTO = new OrderItemDTO();
                    itemDTO.setProductId(item.getProductId());
                    itemDTO.setProductName(item.getProductName());
                    itemDTO.setProductDescription(item.getProductDescription());
                    itemDTO.setPrice(item.getProductPrice());
                    itemDTO.setQuantity(item.getQuantity());
                    itemDTO.setProductImage(item.getProductImage());
                    itemDTO.setSellerId(item.getSellerId());
                    itemDTO.setSellerName(item.getSellerName());
                    return itemDTO;
                }).collect(Collectors.toList());
                dto.setItems(itemDTOs);
            }

            return dto;
        }).collect(Collectors.toList());
    }
    @Override
    public List<OrderDTO> getOrdersByProductName(String productName) {
        List<Order> orders = orderMapper.selectOrdersByProductNameLike(productName);
        if (orders.isEmpty()) {
            return Collections.emptyList();
        }
        List<Integer> orderIds = orders.stream().map(Order::getOrderId).collect(Collectors.toList());
        List<OrderItem> allItems = orderMapper.selectOrderItemsByOrderIds(orderIds);
        Map<Integer, List<OrderItem>> itemsMap = allItems.stream()
                .collect(Collectors.groupingBy(OrderItem::getOrderId));
        List<Integer> addressIds = orders.stream().map(Order::getAddressId).distinct().collect(Collectors.toList());
        List<Address> addresses = userFeignClient.getAddressesByIds(addressIds);
        Map<Integer, Address> addressMap = addresses.stream().collect(Collectors.toMap(Address::getAddressId, a -> a));
        return orders.stream().map(order -> {
            OrderDTO dto = new OrderDTO();
            dto.setOrderId(order.getOrderId());
            dto.setOrderNumber(order.getOrderNumber());
            dto.setUserId(order.getUserId());
            dto.setTotalPrice(order.getTotalPrice());
            dto.setStatus(order.getStatus());
            dto.setCreateTime(order.getCreateTime());
            dto.setPaymentTime(order.getPaymentTime());
            dto.setDeliveryTime(order.getDeliveryTime());
            dto.setCompleteTime(order.getCompleteTime());
            // 设置地址
            Address address = addressMap.get(order.getAddressId());
            if (address != null) {
                AddressDTO addressDTO = new AddressDTO();
                addressDTO.setRecipient(address.getRecipient());
                addressDTO.setPhone(address.getPhone());
                addressDTO.setFullAddress(
                        address.getProvince() + address.getCity() +
                                address.getDistrict() + address.getStreet() + address.getDetail());
                dto.setAddress(addressDTO);
            }
            // 设置订单项
            List<OrderItem> items = itemsMap.get(order.getOrderId());
            if (items != null) {
                List<OrderItemDTO> itemDTOs = items.stream().map(item -> {
                    OrderItemDTO itemDTO = new OrderItemDTO();
                    itemDTO.setProductId(item.getProductId());
                    itemDTO.setProductName(item.getProductName());
                    itemDTO.setProductDescription(item.getProductDescription());
                    itemDTO.setPrice(item.getProductPrice());
                    itemDTO.setQuantity(item.getQuantity());
                    itemDTO.setProductImage(item.getProductImage());
                    itemDTO.setSellerId(item.getSellerId());
                    itemDTO.setSellerName(item.getSellerName());
                    return itemDTO;
                }).collect(Collectors.toList());
                dto.setItems(itemDTOs);
            }
            return dto;
        }).collect(Collectors.toList());
    }

    @Override
    public IPage<OrderDTO> selectPage(Page<Order> pageParam, OrderQueryVo orderQueryVo) {
        // 1. 查询订单分页数据
        IPage<Order> orderPage = orderMapper.selectPage(pageParam, orderQueryVo);
        List<Order> records = orderPage.getRecords();

        if (records.isEmpty()) {
            // 如果没有记录，返回空页
            return new Page<>(pageParam.getCurrent(), pageParam.getSize(), 0);
        }

        // 2. 获取订单ID列表
        List<Integer> orderIds = records.stream()
                .map(Order::getOrderId)
                .collect(Collectors.toList());

        // 3. 批量查询订单项
        List<OrderItem> allItems = orderMapper.selectOrderItemsByOrderIds(orderIds);
        Map<Integer, List<OrderItem>> itemsMap = allItems.stream()
                .collect(Collectors.groupingBy(OrderItem::getOrderId));

        // 4. 获取地址ID列表
        List<Integer> addressIds = records.stream()
                .map(Order::getAddressId)
                .distinct()
                .collect(Collectors.toList());

        // 5. 批量查询地址信息
        List<Address> addresses = userFeignClient.getAddressesByIds(addressIds);
        Map<Integer, Address> addressMap = addresses.stream()
                .collect(Collectors.toMap(Address::getAddressId, a -> a));

        // 6. 转换成DTO
        List<OrderDTO> orderDTOs = records.stream().map(order -> {
            List<OrderItem> items = itemsMap.getOrDefault(order.getOrderId(), Collections.emptyList());
            Address address = addressMap.get(order.getAddressId());
            return convertToDTO(order, items, address);
        }).collect(Collectors.toList());

        // 7. 创建DTO分页结果
        Page<OrderDTO> dtoPage = new Page<>(pageParam.getCurrent(), pageParam.getSize(), orderPage.getTotal());
        dtoPage.setRecords(orderDTOs);

        return dtoPage;
    }
    @Override
    public Order getById(Integer id) {
        return orderMapper.selectById(id);
    }

    @Override
    public void updateById(Order order) {
        orderMapper.updateById(order);
    }


    @Override
    public Order getByPayTradeNo(String payTradeNo) {
        return orderMapper.selectByPayTradeNo(payTradeNo);
    }
}

